/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <atomic>
#include <chrono>
#include <gtest/gtest.h>
#include <mc/log.h>
#include <memory>
#include <mutex>
#include <test_utilities/test_base.h>
#include <thread>
#include <vector>

#include "../../../drivers/scanner/scanner/scanner.h"
#include "../test_utils/root_object.h"

using namespace dev;
using namespace devmon;

namespace drivers {
namespace scanner {
namespace test {

// 模拟Chip接口 - 参照gen::Chip的实现方式
class mock_chip_interface : public mc::engine::interface<mock_chip_interface> {
public:
    MC_INTERFACE("org.test.MockChipInterface")

    // 定义属性，用于存储最后的读写操作
    mc::engine::property<uint32_t>             last_read_offset;
    mc::engine::property<uint32_t>             last_read_length;
    mc::engine::property<uint32_t>             last_write_offset;
    mc::engine::property<std::vector<uint8_t>> last_write_data;

    mock_chip_interface() {
        last_read_offset  = 0;
        last_read_length  = 0;
        last_write_offset = 0;
        last_write_data   = std::vector<uint8_t>();
    }

    // 实现BlockIO方法
    std::vector<uint8_t> BlockIORead(const uint32_t& offset, const uint32_t& length) {
        // 记录读取操作
        last_read_offset = offset;
        last_read_length = length;

        // 模拟读取失败的情况
        if (offset == 0xDEAD) {
            MC_THROW(mc::system_exception, "Read failed");
        }

        // 返回测试数据：根据offset生成不同的数据
        std::vector<uint8_t> data;
        for (uint32_t i = 0; i < length; ++i) {
            data.push_back(static_cast<uint8_t>((offset + i) & 0xFF));
        }
        return data;
    }

    void BlockIOWrite(const uint32_t& offset, const std::vector<uint8_t>& buffer) {
        // 模拟写入失败的情况
        if (offset == 0xBEEF) {
            MC_THROW(mc::system_exception, "Write failed");
        }

        // 保存写入的数据用于验证
        last_write_offset = offset;
        last_write_data   = buffer;
    }
};

// 模拟Chip对象
class mock_chip : public mc::engine::object<mock_chip> {
public:
    MC_OBJECT(mock_chip, "MockChip", "/bmc/topology/MockChip", (mock_chip_interface))

    mock_chip() = default;

    mock_chip_interface m_interface;

    // 返回接口引用
    mock_chip_interface& get_interface() {
        return m_interface;
    }

    static mc::shared_ptr<mock_chip> create() {
        return mc::make_shared<mock_chip>();
    }
};

// 异常模拟Chip对象 - 用于测试异常处理
class exception_mock_chip : public mc::engine::object<exception_mock_chip> {
public:
    MC_OBJECT(exception_mock_chip, "ExceptionMockChip", "/bmc/topology/ExceptionMockChip",
              (mock_chip_interface))

    exception_mock_chip() = default;

    mock_chip_interface m_interface;

    // 返回接口引用
    mock_chip_interface& get_interface() {
        return m_interface;
    }

    static mc::shared_ptr<exception_mock_chip> create() {
        return mc::make_shared<exception_mock_chip>();
    }
};

// 动态模拟Chip接口 - 用于测试数据变化
class dynamic_mock_chip_interface : public mc::engine::interface<dynamic_mock_chip_interface> {
public:
    MC_INTERFACE("org.test.DynamicMockChipInterface")

    // 定义属性，用于存储最后的读写操作
    mc::engine::property<uint32_t>             last_read_offset;
    mc::engine::property<uint32_t>             last_read_length;
    mc::engine::property<uint32_t>             last_write_offset;
    mc::engine::property<std::vector<uint8_t>> last_write_data;

    dynamic_mock_chip_interface() : m_read_counter(0) {
        last_read_offset  = 0;
        last_read_length  = 0;
        last_write_offset = 0;
        last_write_data   = std::vector<uint8_t>();
    }

    // 实现BlockIO方法，每次读取返回不同的数据
    std::vector<uint8_t> BlockIORead(const uint32_t& offset, const uint32_t& length) {
        // 记录读取操作
        last_read_offset = offset;
        last_read_length = length;

        // 增加读取计数器
        m_read_counter++;

        // 返回基于计数器的变化数据
        std::vector<uint8_t> data;
        for (uint32_t i = 0; i < length; ++i) {
            // 使用计数器来生成变化的数据
            data.push_back(static_cast<uint8_t>((offset + i + m_read_counter) & 0xFF));
        }
        return data;
    }

    void BlockIOWrite(const uint32_t& offset, const std::vector<uint8_t>& buffer) {
        // 保存写入的数据用于验证
        last_write_offset = offset;
        last_write_data   = buffer;
    }

    // 获取读取计数器
    uint32_t get_read_counter() const {
        return m_read_counter;
    }

private:
    std::atomic<uint32_t> m_read_counter;
};

// 动态模拟Chip对象
class dynamic_mock_chip : public mc::engine::object<dynamic_mock_chip> {
public:
    MC_OBJECT(dynamic_mock_chip, "DynamicMockChip", "/bmc/topology/DynamicMockChip",
              (dynamic_mock_chip_interface))

    dynamic_mock_chip() = default;

    dynamic_mock_chip_interface m_interface;

    // 返回接口引用
    dynamic_mock_chip_interface& get_interface() {
        return m_interface;
    }

    static mc::shared_ptr<dynamic_mock_chip> create() {
        return mc::make_shared<dynamic_mock_chip>();
    }
};

// 测试服务
class scanner_test_service : public mc::engine::service {
public:
    scanner_test_service(const std::string& name) : mc::engine::service(name) {
    }
};

// 使用devmon命名空间中的根对象定义

class ScannerTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = mc::make_shared<scanner_test_service>("bmc.kepler.test_scanner");
        m_test_service->init();
        m_test_service->start();

        // 创建根对象
        m_root_object = root_object::create_root_object(m_test_service.get());
    }

    static void TearDownTestSuite() {
        m_test_service->stop();
        m_root_object.reset();
        m_test_service.reset();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        // 创建模拟的Chip对象 - 使用与test_accessor.cpp相同的模式
        mc::mutable_dict functions;
        m_mock_chip = mock_chip::create();
        m_mock_chip->set_position("97");
        m_mock_chip->set_object_name("MockChip_97");
        m_test_service->register_object(m_mock_chip);

        // 创建Scanner对象
        m_scanner = mc::make_shared<Scanner>();
        m_scanner->set_position("97");
        m_scanner->set_object_name("Scanner");
        m_test_service->register_object(m_scanner);

        m_exception_chip = exception_mock_chip::create();
        m_exception_chip->set_position("97");
        m_exception_chip->set_object_name("ExceptionMockChip_97");
        m_test_service->register_object(m_exception_chip);

        // 创建动态mock chip用于测试数据变化
        m_dynamic_chip = dynamic_mock_chip::create();
        m_dynamic_chip->set_position("97");
        m_dynamic_chip->set_object_name("DynamicMockChip_97");
        m_test_service->register_object(m_dynamic_chip);

        // 保存chip名称用于引用
        m_chip_name         = std::string(m_mock_chip->get_object_name());
        m_dynamic_chip_name = std::string(m_dynamic_chip->get_object_name());

        // 创建std::shared_ptr来管理服务，用于func_collection
        std::shared_ptr<mc::engine::service> service_ptr(m_test_service.get(),
                                                         [](mc::engine::service*) {
                                                         });
        func_collection::get_instance().add("97", service_ptr, functions);
    }

    void TearDown() override {
        if (m_scanner) {
            m_scanner->stop();
            m_test_service->unregister_object(std::string(m_scanner->get_object_path()));
            m_scanner.reset();
        }
        if (m_mock_chip) {
            m_test_service->unregister_object(std::string(m_mock_chip->get_object_path()));
            m_mock_chip.reset();
        }
        if (m_exception_chip) {
            m_test_service->unregister_object(std::string(m_exception_chip->get_object_path()));
            m_exception_chip.reset();
        }
        if (m_dynamic_chip) {
            m_test_service->unregister_object(std::string(m_dynamic_chip->get_object_path()));
            m_dynamic_chip.reset();
        }
    }

    // 创建测试用的CSR配置
    mc::mutable_dict create_test_csr() {
        mc::mutable_dict csr;
        csr["Chip"] =
            "#/" + m_chip_name.substr(
                       0, m_chip_name.find("_")); // 使用对象名作为引用，参照test_accessor.cpp
        csr["Offset"] = static_cast<uint32_t>(0x100);
        csr["Size"]   = static_cast<uint8_t>(4);
        csr["Mask"]   = static_cast<uint8_t>(0xFF);
        csr["Type"]   = static_cast<uint8_t>(1);
        csr["Period"] = static_cast<uint32_t>(1000);
        return csr;
    }

    mc::dict create_test_connector() {
        mc::dict connector{{"SystemId", 1}, {"Position", 1}, {"Slot", 1}};
        return connector;
    }

    // 辅助函数：设置Chip对象引用
    void set_chip_reference() {
        // 设置引用路径，格式为 #/ + 对象名（参照test_accessor.cpp）
        std::string chip_ref_path = "#/" + m_chip_name.substr(0, m_chip_name.find("_"));
        mc::variant ref_obj{chip_ref_path};
        from_variant(ref_obj, m_scanner->i_scanner.Chip);
    }

protected:
    static mc::shared_ptr<scanner_test_service> m_test_service;
    static root_object_ptr                      m_root_object;
    mc::shared_ptr<mock_chip>                   m_mock_chip;
    mc::shared_ptr<Scanner>                     m_scanner;
    mc::shared_ptr<exception_mock_chip>         m_exception_chip;
    mc::shared_ptr<dynamic_mock_chip>           m_dynamic_chip;
    std::string                                 m_chip_name;
    std::string                                 m_dynamic_chip_name;
};

mc::shared_ptr<scanner_test_service> ScannerTest::m_test_service;
root_object_ptr                      ScannerTest::m_root_object;

// ========================= Scanner基本功能测试 =========================

TEST_F(ScannerTest, test_basic_init) {
    // 使用SetUp()中创建的Scanner对象，避免位置ID不匹配
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool result = m_scanner->init(csr, connector);
    EXPECT_TRUE(result);

    // 验证属性是否正确设置
    EXPECT_EQ(m_scanner->i_scanner.Offset.get_value(), 0x100);
    EXPECT_EQ(m_scanner->i_scanner.Size.get_value(), 4);
    EXPECT_EQ(m_scanner->i_scanner.Mask.get_value(), 0xFF);
    EXPECT_EQ(m_scanner->i_scanner.Type.get_value(), 1);
    EXPECT_EQ(m_scanner->i_scanner.Period.get_value(), 1000);
}

TEST_F(ScannerTest, test_init_missing_fields) {
    mc::mutable_dict csr;
    // 缺少必需的字段
    csr["Chip"]   = "#/" + m_chip_name.substr(0, m_chip_name.find("_"));
    csr["Offset"] = static_cast<uint32_t>(0x100);
    // 缺少其他字段

    auto connector = create_test_connector();

    bool result = m_scanner->init(csr, connector);
    EXPECT_FALSE(result);
}

TEST_F(ScannerTest, test_start_stop_scanner) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 设置Chip对象引用
    set_chip_reference();

    // 启动Scanner
    bool start_result = m_scanner->start();
    EXPECT_TRUE(start_result);

    // 等待一小段时间确保定时器已经启动
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    // 停止Scanner
    bool stop_result = m_scanner->stop();
    EXPECT_TRUE(stop_result);

    // 等待定时器完全停止
    std::this_thread::sleep_for(std::chrono::milliseconds(300));
}

TEST_F(ScannerTest, test_start_without_init) {
    // 使用一个新的Scanner对象，不初始化就启动应该失败
    auto test_scanner = mc::make_shared<Scanner>();
    test_scanner->set_position("97");
    test_scanner->set_object_name("TestScanner_StartWithoutInit");
    m_test_service->register_object(test_scanner);

    bool start_result = test_scanner->start();
    EXPECT_FALSE(start_result);

    // 清理测试对象
    m_test_service->unregister_object(std::string(test_scanner->get_object_path()));
}

TEST_F(ScannerTest, test_stop_without_start) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 未启动就停止应该成功
    bool stop_result = m_scanner->stop();
    EXPECT_TRUE(stop_result);
}

TEST_F(ScannerTest, test_multiple_start_stop) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 设置Chip对象引用
    set_chip_reference();

    // 启动和停止
    bool start_result = m_scanner->start();
    EXPECT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(300));

    bool stop_result = m_scanner->stop();
    EXPECT_TRUE(stop_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(200));
}

// ========================= Scanner周期性读取测试 =========================

TEST_F(ScannerTest, test_periodic_reading_single_cycle) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 设置Chip对象引用
    set_chip_reference();

    // 启动Scanner
    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    // 等待至少一个周期（1000ms + 一些余量）
    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    // 验证是否调用了BlockIORead
    EXPECT_GT(m_mock_chip->m_interface.last_read_offset.get_value(), 0);
    EXPECT_EQ(m_mock_chip->m_interface.last_read_offset.get_value(), 0x100);
    EXPECT_EQ(m_mock_chip->m_interface.last_read_length.get_value(), 4);

    // 验证Value是否正确更新
    uint64_t value = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    EXPECT_EQ(value, 0x03020100ULL); // mock_chip返回的数据转换为小端序

    // 验证Status是否为成功
    uint8_t status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(status, 0);

    // 停止Scanner
    m_scanner->stop();
}

TEST_F(ScannerTest, test_periodic_reading_multiple_cycles) {
    // 创建更短周期的配置以加快测试
    mc::mutable_dict csr;
    csr["Chip"] =
        "#/" + m_chip_name.substr(0, m_chip_name.find("_")); // 使用对象名作为引用，类似ABI测试
    csr["Offset"] = static_cast<uint32_t>(0x200);
    csr["Size"]   = static_cast<uint8_t>(2);
    csr["Mask"]   = static_cast<uint8_t>(0xFF);
    csr["Type"]   = static_cast<uint8_t>(1);
    csr["Period"] = static_cast<uint32_t>(300); // 300ms周期，更安全

    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 设置Chip对象引用
    set_chip_reference();

    // 启动Scanner
    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    // 等待多个周期（4个周期 = 1200ms + 余量）
    std::this_thread::sleep_for(std::chrono::milliseconds(1400));

    // 验证是否调用了BlockIORead，且参数正确
    EXPECT_EQ(m_mock_chip->m_interface.last_read_offset.get_value(), 0x200);
    EXPECT_EQ(m_mock_chip->m_interface.last_read_length.get_value(), 2);

    // 验证Value是否正确更新（offset=0x200, size=2的数据）
    uint64_t value = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    EXPECT_EQ(value, 0x0100ULL); // [0x00, 0x01]转换为小端序

    // 验证Status是否为成功
    uint8_t status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(status, 0);

    // 停止Scanner
    m_scanner->stop();
}

TEST_F(ScannerTest, test_periodic_reading_value_changes) {
    // 创建更短周期的配置以便快速观察变化
    mc::mutable_dict csr;
    // 使用动态chip的类型名作为引用，与其他测试用例保持一致
    csr["Chip"]   = "#/" + m_dynamic_chip_name.substr(0, m_dynamic_chip_name.find("_"));
    csr["Offset"] = static_cast<uint32_t>(0x200);
    csr["Size"]   = static_cast<uint8_t>(4);
    csr["Mask"]   = static_cast<uint8_t>(0xFF);
    csr["Type"]   = static_cast<uint8_t>(1);
    csr["Period"] = static_cast<uint32_t>(200); // 200ms周期

    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    // 设置动态Chip对象引用，使用类型名（系统会自动添加位置信息）
    std::string dynamic_chip_ref_path =
        "#/" + m_dynamic_chip_name.substr(0, m_dynamic_chip_name.find("_"));
    mc::variant dynamic_ref_obj{dynamic_chip_ref_path};
    from_variant(dynamic_ref_obj, m_scanner->i_scanner.Chip);

    // 启动Scanner
    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    // 等待第一次读取
    std::this_thread::sleep_for(std::chrono::milliseconds(300));

    // 获取第一次读取的值
    uint64_t first_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  first_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(first_status, 0);

    // 等待更多周期，让Scanner继续读取
    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    // 获取第二次读取的值
    uint64_t second_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  second_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(second_status, 0);

    // 验证值发生了变化
    EXPECT_NE(first_value, second_value);

    // 再等待一段时间，获取第三次读取的值
    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    uint64_t third_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  third_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(third_status, 0);

    // 验证第三次的值与前两次都不同
    EXPECT_NE(first_value, third_value);
    EXPECT_NE(second_value, third_value);

    // 验证读取计数器确实在增加
    uint32_t read_count = m_dynamic_chip->m_interface.get_read_counter();
    EXPECT_GT(read_count, 2); // 至少读取了3次

    // 验证最后一次读取的参数
    EXPECT_EQ(m_dynamic_chip->m_interface.last_read_offset.get_value(), 0x200);
    EXPECT_EQ(m_dynamic_chip->m_interface.last_read_length.get_value(), 4);

    // 停止Scanner
    m_scanner->stop();
}

TEST_F(ScannerTest, test_high_frequency_scanning) {
    auto csr       = create_test_csr();
    csr["Period"]  = static_cast<uint32_t>(10); // 高频率：10ms
    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    // 启动高频Scanner
    bool start_result = m_scanner->start();
    EXPECT_TRUE(start_result);

    // 短时间运行，避免过度占用资源
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    // 验证Scanner仍能正常工作
    uint8_t status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(status, 0);

    // 验证至少进行了一些读取操作
    EXPECT_GT(m_mock_chip->m_interface.last_read_offset.get_value(), 0);

    m_scanner->stop();
}

// ========================= Scanner异常处理测试 =========================
TEST_F(ScannerTest, test_chip_blockio_exception) {
    // 使用会抛出异常的Chip - 设置offset为0xDEAD来触发异常
    mc::mutable_dict csr;
    csr["Chip"] = "#/" + std::string(m_exception_chip->get_object_name())
                             .substr(0, std::string(m_exception_chip->get_object_name()).find("_"));
    csr["Offset"] = static_cast<uint32_t>(0xDEAD); // 使用会触发异常的偏移量
    csr["Size"]   = static_cast<uint8_t>(4);
    csr["Mask"]   = static_cast<uint8_t>(0xFF);
    csr["Type"]   = static_cast<uint8_t>(1);
    csr["Period"] = static_cast<uint32_t>(500);

    auto connector = create_test_connector();

    // 初始化Scanner
    bool init_result = m_scanner->init(csr, connector);
    m_scanner->i_scanner.FailureDebounceCount.set_value(0);
    ASSERT_TRUE(init_result);

    // 设置异常Chip对象引用
    std::string exception_chip_ref =
        "#/" + std::string(m_exception_chip->get_object_name())
                   .substr(0, std::string(m_exception_chip->get_object_name()).find("_"));
    mc::variant exception_ref_obj{exception_chip_ref};
    from_variant(exception_ref_obj, m_scanner->i_scanner.Chip);

    // 启动Scanner
    bool start_result = m_scanner->start();
    EXPECT_TRUE(start_result);

    // 等待一个周期，让异常发生
    std::this_thread::sleep_for(std::chrono::milliseconds(700));

    // 验证Status应该为错误状态
    uint8_t status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(status, 1);

    m_scanner->stop();
}

// ========================= ScanEnabled属性变更测试 =========================

TEST_F(ScannerTest, test_scanenabled_property_change_enable_to_disable) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    m_scanner->i_scanner.NominalValue.set_value(0x1234567890ABCDEFULL);

    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    uint8_t running_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(running_status, 0);

    m_scanner->i_scanner.ScanEnabled.set_value(0);

    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t stopped_value = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    EXPECT_EQ(stopped_value, 0x1234567890ABCDEFULL);

    uint8_t stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(stopped_status, 3);

    uint64_t last_read_offset_before =
        m_mock_chip->m_interface.last_read_offset.get_value().as<uint64_t>();
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    uint64_t last_read_offset_after =
        m_mock_chip->m_interface.last_read_offset.get_value().as<uint64_t>();
    EXPECT_EQ(last_read_offset_before, last_read_offset_after);

    m_scanner->stop();
}

TEST_F(ScannerTest, test_scanenabled_property_change_disable_to_enable) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    m_scanner->i_scanner.NominalValue.set_value(0x9876543210FEDCBAULL);

    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    m_scanner->stop();
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t stopped_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(stopped_value, 0x9876543210FEDCBAULL);
    EXPECT_EQ(stopped_status, 3);

    uint64_t value_before = m_scanner->i_scanner.Value.get_value().as<uint64_t>();

    m_scanner->i_scanner.ScanEnabled.set_value(1);

    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));
    uint64_t value_after = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    EXPECT_NE(value_after, value_before);

    uint8_t running_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(running_status, 0);

    m_scanner->stop();
}

TEST_F(ScannerTest, test_scanenabled_property_change_multiple_toggles) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    m_scanner->i_scanner.NominalValue.set_value(0xDEADBEEFCAFEBABEULL);

    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    m_scanner->i_scanner.ScanEnabled.set_value(0);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t first_stopped_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  first_stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(first_stopped_value, 0xDEADBEEFCAFEBABEULL);
    EXPECT_EQ(first_stopped_status, 3);

    m_scanner->i_scanner.ScanEnabled.set_value(1);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    uint8_t first_running_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(first_running_status, 0);

    m_scanner->i_scanner.ScanEnabled.set_value(0);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t second_stopped_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  second_stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(second_stopped_value, 0xDEADBEEFCAFEBABEULL);
    EXPECT_EQ(second_stopped_status, 3);

    m_scanner->i_scanner.ScanEnabled.set_value(1);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    uint8_t final_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(final_status, 0);

    m_scanner->stop();
}

TEST_F(ScannerTest, test_scanenabled_property_change_with_nominal_value_zero) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    m_scanner->i_scanner.NominalValue.set_value(0ULL);

    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    uint64_t running_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  running_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_NE(running_value, 0ULL);
    EXPECT_EQ(running_status, 0);

    m_scanner->i_scanner.ScanEnabled.set_value(0);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t stopped_value = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    EXPECT_EQ(stopped_value, 0ULL);

    uint8_t stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(stopped_status, 3);

    m_scanner->stop();
}

TEST_F(ScannerTest, test_scanenabled_property_change_signal_connection) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    bool init_result = m_scanner->init(csr, connector);
    ASSERT_TRUE(init_result);

    set_chip_reference();

    m_scanner->i_scanner.NominalValue.set_value(0x1234567890ABCDEFULL);

    bool start_result = m_scanner->start();
    ASSERT_TRUE(start_result);

    std::this_thread::sleep_for(std::chrono::milliseconds(1200));

    uint64_t initial_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  initial_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_NE(initial_value, 0x1234567890ABCDEFULL);
    EXPECT_EQ(initial_status, 0);

    m_scanner->i_scanner.ScanEnabled.set_value(0);

    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    uint64_t signal_stopped_value  = m_scanner->i_scanner.Value.get_value().as<uint64_t>();
    uint8_t  signal_stopped_status = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(signal_stopped_value, 0x1234567890ABCDEFULL);
    EXPECT_EQ(signal_stopped_status, 3);

    m_scanner->stop();
}

TEST_F(ScannerTest, test_handle_result_failure_through_reading_failure) {
    auto csr       = create_test_csr();
    auto connector = create_test_connector();

    mc::mutable_dict failure_csr;
    failure_csr["Chip"] = "#/" + std::string(m_exception_chip->get_object_name())
                                 .substr(0, std::string(m_exception_chip->get_object_name()).find("_"));
    failure_csr["Offset"] = static_cast<uint32_t>(0xDEAD); // 使用会触发异常的偏移量
    failure_csr["Size"]   = static_cast<uint8_t>(4);
    failure_csr["Mask"]   = static_cast<uint8_t>(0xFF);
    failure_csr["Type"]   = static_cast<uint8_t>(1);
    failure_csr["Period"] = static_cast<uint32_t>(500);

    // 初始化Scanner
    bool init_result = m_scanner->init(failure_csr, connector);
    m_scanner->i_scanner.FailureDebounceCount.set_value(2);
    ASSERT_TRUE(init_result);

    // 设置异常Chip对象引用
    std::string exception_chip_ref =
        "#/" + std::string(m_exception_chip->get_object_name())
                   .substr(0, std::string(m_exception_chip->get_object_name()).find("_"));
    mc::variant exception_ref_obj{exception_chip_ref};
    from_variant(exception_ref_obj, m_scanner->i_scanner.Chip);

    // 重新启动Scanner
    bool restart_result = m_scanner->start();
    ASSERT_TRUE(restart_result);

    // 等待第一次失败读取
    std::this_thread::sleep_for(std::chrono::milliseconds(700));
    uint8_t status_after_one_failure = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    elog("status_after_one_failure: ${status}", ("status", status_after_one_failure));
    EXPECT_EQ(status_after_one_failure, SCANNER_PRE_FAILURE);

    // 等待第二次失败读取
    std::this_thread::sleep_for(std::chrono::milliseconds(700));
    uint8_t status_after_two_failures = m_scanner->i_scanner.Status.get_value().as<uint8_t>();
    EXPECT_EQ(status_after_two_failures, SCANNER_FAILURE);

    m_scanner->stop();
}

} // namespace test
} // namespace scanner
} // namespace drivers

// 为mock类添加反射支持
MC_REFLECT(drivers::scanner::test::mock_chip_interface,
           ((last_read_offset, "LastReadOffset"))((last_read_length, "LastReadLength"))(
               (last_write_offset, "LastWriteOffset"))((last_write_data, "LastWriteData"))(
               (BlockIORead, "BlockIORead"))((BlockIOWrite, "BlockIOWrite")))
MC_REFLECT(drivers::scanner::test::mock_chip, ((m_interface, "interface")))
MC_REFLECT(drivers::scanner::test::exception_mock_chip, ((m_interface, "interface")))
MC_REFLECT(drivers::scanner::test::dynamic_mock_chip_interface,
           ((last_read_offset, "LastReadOffset"))((last_read_length, "LastReadLength"))(
               (last_write_offset, "LastWriteOffset"))((last_write_data, "LastWriteData"))(
               (BlockIORead, "BlockIORead"))((BlockIOWrite, "BlockIOWrite")))
MC_REFLECT(drivers::scanner::test::dynamic_mock_chip, ((m_interface, "interface")))